import type { Metadata } from "next"; import Link from "next/link"; import { notFound } from "next/navigation"; import { Breadcrumbs } from "@/components/entity/breadcrumbs"; import { EntityMap } from "@/components/entity/entity-map"; import { JsonLd } from "@/components/entity/json-ld"; import { ExtLink, KeyValueList } from "@/components/entity/kv"; import { SectionNav } from "@/components/entity/section-nav"; import { SourcesFooter } from "@/components/entity/sources-footer"; import { FacilityTable } from "@/components/facility-table"; import { ApiNote, HonestEmpty, ShareList } from "@/components/intelligence/shared"; import { StatusBadge } from "@/components/ui/badge"; import { Page, Section } from "@/components/ui/card"; import { CountryFlag } from "@/components/ui/country-flag"; import { Metric, MetricCell, MetricRow } from "@/components/ui/metric"; import { OfflineNotice } from "@/components/ui/states"; import { RowLink, TBody, THead, Table, Td, Th, Tr } from "@/components/ui/table"; import { SourceHistory } from "@/components/ui/timeline"; import { api } from "@/lib/api"; import { countryName, fmtInt, placeLine, pluralize } from "@/lib/format"; import { routes } from "@/lib/routes"; import { NOT_FOUND_METADATA, absoluteUrl, compactJsonLd, pageMetadata } from "@/lib/seo"; import { countryHrefMap } from "../../cloud-regions/cloud-format"; export const revalidate = 300; type Params = Promise<{ slug: string }>; function describe(d: { name: string; nameLong: string | null; city: string | null; countryIso2: string | null; networkCount: number | null; facilityCount: number; operators?: unknown[] }): string { const place = [d.city, d.countryIso2 ? countryName(d.countryIso2) : null].filter(Boolean).join(", "); const parts = [`${d.name}${d.nameLong && d.nameLong !== d.name ? ` (${d.nameLong})` : ""} — internet exchange point${place ? ` in ${place}` : ""}`]; if (d.networkCount !== null) parts.push(`${fmtInt(d.networkCount)} connected networks`); parts.push(`present in ${fmtInt(d.facilityCount)} indexed ${d.facilityCount === 1 ? "facility" : "facilities"}`); if (d.operators?.length) parts.push(`${fmtInt(d.operators.length)} operators`); return `${parts.join(", ")}. Facilities, operators, nearby infrastructure and sources.`; } /** External identifier → public URL when the registry is known. */ function idHref(key: string, value: string | number): string | null { const k = key.toLowerCase(); if (k.includes("peeringdb")) return `https://www.peeringdb.com/ix/${value}`; if (k === "wikidata") return `https://www.wikidata.org/wiki/${value}`; if (typeof value === "string" && /^https?:\/\//.test(value)) return value; return null; } export async function generateMetadata({ params }: { params: Params }): Promise { const { slug } = await params; const r = await api.ixp(slug); if (!r.ok) return r.status === 404 ? NOT_FOUND_METADATA : { title: "Internet exchange" }; return pageMetadata({ title: r.data.name, description: describe(r.data), path: routes.ixp(r.data.slug) }); } export default async function IxpPage({ params }: { params: Params }) { const { slug } = await params; const [r, countryHref] = await Promise.all([api.ixp(slug), countryHrefMap()]); if (!r.ok && r.status === 404) notFound(); if (!r.ok) { return ( ); } const d = r.data; const cName = d.countryName ?? (d.countryIso2 ? countryName(d.countryIso2) : null); const cHref = countryHref(d.countryIso2); const ids = Object.entries(d.externalIds ?? {}); const facilities = d.facilities ?? []; const operators = [...(d.operators ?? [])].sort((a, b) => b.facilityCount - a.facilityCount); const opTotal = operators.reduce((a, o) => a + o.facilityCount, 0) || 1; const nearby = d.nearbyFacilities ?? []; const hasGeo = typeof d.lat === "number" && typeof d.lng === "number"; const history = d.sourceHistory ?? []; const jsonLd = compactJsonLd({ "@context": "https://schema.org", "@type": "Organization", name: d.name, alternateName: d.nameLong && d.nameLong !== d.name ? d.nameLong : undefined, url: absoluteUrl(routes.ixp(d.slug)), sameAs: [d.website, ...ids.map(([k, v]) => idHref(k, v))].filter((x): x is string => !!x), description: describe(d), address: d.city || cName ? compactJsonLd({ "@type": "PostalAddress", addressLocality: d.city, addressCountry: d.countryIso2 }) : undefined, }); const sections = [ { id: "location", label: "Location" }, { id: "facilities", label: "Facilities", count: facilities.length }, { id: "operators", label: "Operators", count: operators.length }, { id: "nearby", label: "Nearby infrastructure" }, { id: "identifiers", label: "Identifiers", count: ids.length }, { id: "history", label: "Source history", count: history.length }, ]; return (
Internet exchange

{d.name}

{d.nameLong && d.nameLong !== d.name &&

{d.nameLong}

}

{d.countryIso2 && } {d.city && {d.city}} {cName && ( <> {d.city && ·} {cHref ? ( {cName} ) : ( {cName} )} )} {d.metro && ( <> · {d.metro.name} market )} {d.website && ( <> · )}

{hasGeo ? : the exchange is placed in the {d.metro.name} market on maps : "no metro reference either — the exchange is listed but not mapped"} />}
{cName} : cName) : null }, { label: "Market", value: d.metro ? {d.metro.name} : null }, { label: "Website", value: d.website ? : null }, ]} columns={2} />
{facilities.length ? : }
{operators.length ? ({ key: o.id, label: o.name, href: routes.operator(o.slug), count: o.facilityCount, share: o.facilityCount / opTotal }))} /> : }
{nearby.length ? ( {nearby.map((f) => ( ))}
Facility Operator Place Status Distance
{f.name}
{f.operator?.name ?? "Operator unknown"}
{f.operator ? ( {f.operator.name} ) : ( — )} {placeLine(f)} {f.distanceKm < 1 ? `${Math.round(f.distanceKm * 1000)} m` : `${f.distanceKm.toFixed(1)} km`}
) : ( )}
{ids.length ? ( { const href = idHref(k, v); return { label: k.replace(/_/g, " "), value: href ? {String(v)} : {String(v)} }; })} columns={2} /> ) : ( )}
{history.length ? : }
); }